import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

class ThreadServer {
	private static ServerSocket welcomeSocket;

	public static void main(String args[]) throws IOException {
		int port_number = 0;
		int option = 0;
			
		while (true) {																	//take input from user, Port Number
			   System.out.println("SERVER SIDE");
			   System.out.println("Enter the port number for TCP/IP connection: ");
			   BufferedReader br = new BufferedReader(new InputStreamReader(System.in));  
			   port_number = Integer.parseInt(br.readLine());
			   System.out.println("Now using port number ="+port_number);
			   if (	port_number < 65535 || port_number > 0)
			      break;
			   else
			      System.out.println("Invalid port number. Choose from 0 - 65535");
			}
		while (true) {																		//take input from user, Option Number
			   System.out.println("OPTION-1 :Non-persistent without parallel connections");
			   System.out.println("OPTION-2 :Non-persistent with parallel connections");
			   System.out.println("OPTION-3 :Persistent without pipelining");
			   System.out.println("OPTION-4 :Persistent with pipelining");
			   System.out.println("Enter the option number for TCP/IP connection: ");
			   BufferedReader br = new BufferedReader(new InputStreamReader(System.in));  
			   option = Integer.parseInt(br.readLine());
			   System.out.println("Now using option number ="+option);
			   if (	option < 5 || option > 0)
			      break;
			   else
			      System.out.println("Invalid option number. Choose from 1-4");
			}
		try {
			welcomeSocket = new ServerSocket(port_number);							//open server socket at given port number
			Socket serverSocket = null;
			DataOutputStream outToClient1 = null;
			BufferedReader inFromClient = null;
			while (true) {
				if (option == 3 || option == 4) {
					if (serverSocket == null || serverSocket.isClosed()) {
						serverSocket = welcomeSocket.accept();
						outToClient1 = new DataOutputStream(
								serverSocket.getOutputStream());
						inFromClient = new BufferedReader(
								new InputStreamReader(
										serverSocket.getInputStream()));
					}
					(new Server_Thread(serverSocket, option, outToClient1,
							inFromClient)).run();							//create and run new thread
				} else {
					Thread t = new Thread (new Server_Thread(welcomeSocket.accept()));
					t.start();												//
				}
			}
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}
}

// SERVER THREAD
class Server_Thread implements  Runnable {
	private Socket connectionSocket = null;
	private int option;
	private DataOutputStream outToClient1 = null;
	private BufferedReader is1 = null;

	public Server_Thread(Socket connectionSocket) {					//Constructor 
		this.connectionSocket = connectionSocket;
	}

	public Server_Thread(Socket connectionSocket, int option) {   //Constructor
		this.connectionSocket = connectionSocket;
		this.option = option;
	}

	public Server_Thread(Socket connectionSocket, int option,            //Constructor
			DataOutputStream outToClient1, BufferedReader is1) {
		this.connectionSocket = connectionSocket;
		this.option = option;
		this.outToClient1 = outToClient1;
		this.is1 = is1;
	}

	public void run() {												//run method 
		BufferedReader inFromClient = null;
		DataOutputStream outToClient = null;
		try {
			if (this.option == 3 || this.option == 4) {
				String clientRequest;
				do {
					clientRequest = null;
					if (this.is1 != null) {
						clientRequest = this.is1.readLine();

						if (clientRequest != null) {
							System.out.println(clientRequest);

							if (clientRequest.equals("Default")
									&& this.outToClient1 != null) {
								getFileList(outToClient1, connectionSocket);
							} else {
								sendFile(clientRequest, outToClient1);
							}
						}
					}
				} while (clientRequest != null);
				if (this.connectionSocket != null
						&& !this.connectionSocket.isClosed()) {
					this.connectionSocket.close();
				}
			}
			else {
				inFromClient = new BufferedReader(new InputStreamReader(
						this.connectionSocket.getInputStream()));
				String clientRequest = null;
				clientRequest = inFromClient.readLine();
				System.out.println(clientRequest);
				outToClient = new DataOutputStream(
						this.connectionSocket.getOutputStream());

				if (clientRequest.equals("Default") && outToClient != null) {
					getFileList(outToClient, this.connectionSocket);
				} else {
					sendFile(clientRequest, outToClient);
				}
				System.out.println("File sending successful...");
				// File sent, exit the main method
			}
		} catch (Exception ex) {
			System.out.println(ex.getMessage());
			// Do exception handling
		} finally {
			try {
					if (this.connectionSocket!= null && !this.connectionSocket.isClosed())
						this.connectionSocket.close();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				System.out.println(e.getMessage());
			}
		}
	}

//Get filelist method
	public static void getFileList(DataOutputStream outToClient,
			Socket connectionSocket) throws IOException {
		System.out.println("THIS IS file list");
//		getAbsolutePath();
		File myFile = new File(
				"C:\\Users\\Arunabh\\workspace\\CCN2\\src\\Files\\Filelistop.txt");
		byte[] mybytearray = new byte[(int) myFile.length()];
		FileInputStream fis = new FileInputStream(myFile);
		long length = myFile.length();
		BufferedInputStream bis = new BufferedInputStream(fis);
		bis.read(mybytearray, 0, mybytearray.length);
		outToClient.writeLong(length);
		outToClient.write(mybytearray, 0, mybytearray.length);
		outToClient.flush();
		bis.close();
		fis.close();

	}

	//Method : Send file to client
	public static void sendFile(String clientRequest,
			DataOutputStream outToClient) throws IOException {
		File myFile = new File(											
				"C:\\Users\\Arunabh\\workspace\\CCN2\\src\\Files\\"
						+ clientRequest);
		if(myFile.exists()){                                        //Check if file exists
		byte[] mybytearray = new byte[(int) myFile.length()];
		long length = myFile.length();
		FileInputStream fis = new FileInputStream(myFile);
		BufferedInputStream bis = new BufferedInputStream(fis);
		bis.read(mybytearray, 0, mybytearray.length);
		outToClient.writeUTF(clientRequest);							
		outToClient.writeLong(length);								//send length of file to client
		outToClient.write(mybytearray, 0, mybytearray.length);		//write contents of file in Data o/p stream
		outToClient.flush();										// flush data o/p stream
		bis.close();
		fis.close();												//close file stream
		System.out.println("Filelist sending successful...");

		}
		else{														//error handling if file doesnt exists
			System.out.println("File does not exists");   
			outToClient.writeUTF("0");			//send msg to client that file does not exists
		}
	}
}